package responses

import (
	"github.com/edgexfoundry/edgex-go/internal/app/dtos"
	common2 "github.com/edgexfoundry/edgex-go/internal/app/dtos/common"
	"github.com/edgexfoundry/edgex-go/internal/app/models"
	edgexDtos "github.com/edgexfoundry/go-mod-core-contracts/v2/dtos"
	"github.com/edgexfoundry/go-mod-core-contracts/v2/dtos/common"
	"strings"
)

type DevicesResponse[T common2.PageEntity] struct {
	common.BaseResponse `json:",inline"`
	common2.PageInfo[T]
}

// NewDevicesResponse device commands query
func NewDevicesResponse(requestId string, message string, statusCode int, ds []models.Device, page, pageSize int, totalCount uint32) DevicesResponse[dtos.Device] {

	pageInfo := common2.NewPageInfo(page, pageSize, totalCount, ToDeviceDTOs(ds))
	return DevicesResponse[dtos.Device]{
		BaseResponse: common.NewBaseResponse(requestId, message, statusCode),
		//Devices:      ToDeviceDTOs(ds),
		PageInfo: pageInfo,
	}
}

func ToDeviceDTOs(ds []models.Device) []dtos.Device {
	deviceCommands := make([]dtos.Device, len(ds))
	for index, d := range ds {
		deviceCommands[index] = ToDeviceDTO(d)
	}
	return deviceCommands
}

func ToDeviceDTO(d models.Device) dtos.Device {
	return dtos.Device{
		Device:       edgexDtos.FromDeviceModelToDTO(d.Device),
		RegisterTime: d.RegisterTime,
		NodeType:     d.NodeType,
		Enable:       d.Enable,
		Code:         d.Code,
		ProductId:    d.ProductId,
		ProfileId:    d.ProfileId,
		ProductName:  d.ProductName,
		DisplayName:  d.DisplayName,
		Labels:       strings.Join(d.Labels, ","),
		AutoEvents:   ToAutoEventDTOs(d.AutoEvents),
	}
}

type DeviceAddResponse struct {
	common.BaseResponse `json:",inline"`
	Id                  string `json:"id"`
}

// NewDeviceAddResponse device add
func NewDeviceAddResponse(requestId string, message string, statusCode int, id string) DeviceAddResponse {
	return DeviceAddResponse{
		BaseResponse: common.NewBaseResponse(requestId, message, statusCode),
		Id:           id,
	}
}

type DeviceResponse struct {
	common.BaseResponse `json:",inline"`
	Device              dtos.Device `json:"data"`
}

// NewDeviceResponse device get
func NewDeviceResponse(requestId string, message string, statusCode int, device dtos.Device) DeviceResponse {
	return DeviceResponse{
		BaseResponse: common.NewBaseResponse(requestId, message, statusCode),
		Device:       device,
	}
}

type TransportResponse[T common2.PageEntity] struct {
	common.BaseResponse `json:",inline"`
	common2.PageInfo[T]
}

// NewDeviceTransportResponse creates deviceResource response DTO with required fields
func NewDeviceTransportResponse(requestId string, message string, statusCode int, transports []models.Transport, page, pageSize int, totalCount uint32) TransportResponse[dtos.Transport] {
	pageInfo := common2.NewPageInfo(page, pageSize, totalCount, ToTransportDTOs(transports))
	return TransportResponse[dtos.Transport]{
		BaseResponse: common.NewBaseResponse(requestId, message, statusCode),
		PageInfo:     pageInfo,
	}
}

func ToTransportDTOs(ds []models.Transport) []dtos.Transport {
	transports := make([]dtos.Transport, len(ds))
	for index, d := range ds {
		transports[index] = ToTransportDTO(d)
	}
	return transports
}

func ToTransportDTO(a models.Transport) dtos.Transport {
	return dtos.Transport{
		Id:          a.Id,
		Name:        a.Name,
		Type:        a.Type,
		Topic:       a.Topic,
		Description: a.Description,
	}
}

type DeviceCountResponse struct {
	common.BaseResponse `json:",inline"`
	DeviceCount         dtos.DeviceCount `json:"data"`
}

// NewDeviceCountResponse device count get
func NewDeviceCountResponse(requestId string, message string, statusCode int, device dtos.DeviceCount) DeviceCountResponse {
	return DeviceCountResponse{
		BaseResponse: common.NewBaseResponse(requestId, message, statusCode),
		DeviceCount:  device,
	}
}

func ToDeviceCountDTO(a models.DeviceCount) dtos.DeviceCount {
	return dtos.DeviceCount{
		Total:   a.Total,
		Online:  a.Online,
		Offline: a.Offline,
	}
}
